--[[-------------------------------------------------------------------------
  Copyright (c) 2006, Jim Whitehead II <cladhaire@gmail.com>
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are
  met:

      * Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
      * Redistributions in binary form must reproduce the above
        copyright notice, this list of conditions and the following
        disclaimer in the documentation and/or other materials provided
        with the distribution.
      * Neither the name of PerfectRaid nor the names of its contributors 
        may be used to endorse or promote products derived from this software
        without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------]]

local Range = PerfectRaid:NewModule("PerfectRaid-Range")
local frames, rangespell, rate
local prialpha, secalpha, outalpha
local prispell, secspell
local L = PerfectRaidLocals

function Range:Initialize()
	PerfectRaid.defaults.profile.RangeCheck = true
	PerfectRaid.defaults.profile.RangeRate = 0.2
	PerfectRaid.defaults.profile.RangePriAlpha = 1.0
	PerfectRaid.defaults.profile.RangeSecAlpha = 0.6
	PerfectRaid.defaults.profile.RangeOutAlpha = 0.3

	local class = select(2, UnitClass("player"))
	local pri = {
		DRUID = L["Healing Touch"],
		SHAMAN = L["Healing Wave"],
		PRIEST = L["Lesser Heal"],
		PALADIN = L["Holy Light"],
	}

	PerfectRaid.defaults.profile.RangePriSpell = pri[class]
	frames = PerfectRaid.frames
end

function Range:Enable()
	if not PerfectRaid.defaults.profile.RangeCheck then return end
	local class = select(2, UnitClass("player"))

	prispell = PerfectRaid.db.profile.RangePriSpell
	secspell = PerfectRaid.db.profile.RangeSecSpell

	if (prispell or secspell) and PerfectRaid.db.profile.RangeCheck then
		if not self.frame then
			self.frame = CreateFrame("Frame")
		end
		self.frame:SetScript("OnUpdate", self.OnUpdate)
		rate = PerfectRaid.db.profile.RangeRate
		prialpha = PerfectRaid.db.profile.RangePriAlpha
		secalpha = PerfectRaid.db.profile.RangeSecAlpha
		outalpha = PerfectRaid.db.profile.RangeOutAlpha
		prispell = PerfectRaid.db.profile.RangePriSpell
		secspell = PerfectRaid.db.profile.RangeSecSpell

		self:RegisterMessage("DONGLE_PROFILE_CHANGED")
	end
end

function Range:Disable()
	if self.frame then
		self.frame:SetScript("OnUpdate", nil)
	end
	for unit,tbl in pairs(frames) do
		for frame in pairs(tbl) do
			frame:SetAlpha(1.0)
		end
	end
end

function Range:DONGLE_PROFILE_CHANGED(event, addon, svname, name)
	if svname == "PerfectRaidDB" then
		rate = PerfectRaid.db.profile.RangeRate
		prialpha = PerfectRaid.db.profile.RangePriAlpha
		secalpha = PerfectRaid.db.profile.RangeSecAlpha
		outalpha = PerfectRaid.db.profile.RangeOutAlpha
		prispell = PerfectRaid.db.profile.RangePriSpell
		secspell = PerfectRaid.db.profile.RangeSecSpell
		if PerfectRaid.db.profile.RangeCheck then
			self:Enable()
		else
			self:Disable()
		end
	end
end

local alpha = 1
local elapsed = 0
function Range.OnUpdate()
	elapsed = elapsed + arg1

	if elapsed >= rate then
		for unit,tbl in pairs(frames) do
			local prirange = IsSpellInRange(prispell, unit) == 1

			if prirange then
				alpha = prialpha
			elseif secspell and IsSpellInRange(secspell, unit) == 1 then
				alpha = secalpha
			else
				alpha = outalpha
			end

			for frame in pairs(tbl) do
				frame:SetAlpha(alpha)
			end
		end
		elapsed = 0
	end		
end

local options
function Range:CreateOptions(opt)
	options = CreateFrame("Frame", "PROptions_Range", PROptions)
	options:SetScript("OnShow", function() self:OnShow() end)

	opt:AddOptionsTab("Range Check", options)

	options.widgets = {}

	local check = CreateFrame("CheckButton", "PRRange_Enable", options, "PRCheckTemplate")
	check.Label:SetText(L["Perform range checking"])
	table.insert(options.widgets, check)

	local slider = CreateFrame("Slider", "PRRange_Rate", options, "PRSliderTemplate")
	slider.Text:SetText(L["Update delay"])
	slider.High:SetText("2.0")
	slider.Low:SetText("0")
	slider:SetMinMaxValues(0,2.0)
	slider:SetValueStep(0.1)
	table.insert(options.widgets, slider)

	local slider = CreateFrame("Slider", "PRRange_PriAlpha", options, "PRSliderTemplate")
	slider.Text:SetText(L["Primary In-Range Alpha"])
	slider.High:SetText("1")
	slider.Low:SetText("0")
	slider:SetMinMaxValues(0,1)
	slider:SetValueStep(0.05)
	table.insert(options.widgets, slider)

	local slider = CreateFrame("Slider", "PRRange_SecAlpha", options, "PRSliderTemplate")
	slider.Text:SetText(L["Secondary In-Range Alpha"])
	slider.High:SetText("1")
	slider.Low:SetText("0")
	slider:SetMinMaxValues(0,1)
	slider:SetValueStep(0.05)
	table.insert(options.widgets, slider)

	local slider = CreateFrame("Slider", "PRRange_OutAlpha", options, "PRSliderTemplate")
	slider.Text:SetText(L["Out-of-Range Alpha"])
	slider.High:SetText("1")
	slider.Low:SetText("0")
	slider:SetMinMaxValues(0,1)
	slider:SetValueStep(0.05)
	table.insert(options.widgets, slider)

	local widget = CreateFrame("Frame", nil, options)
	widget:SetHeight(35)
	widget:SetWidth(160)
	local editbox = CreateFrame("EditBox", "PRRange_PriSpell", widget, "InputBoxTemplate")
	local font = editbox:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
	font:SetText(L["Primary Spell:"])
	font:SetPoint("TOPLEFT", widget, "TOPLEFT", 0, 0)
	editbox:SetAutoFocus(nil)
	editbox:SetWidth(160)
	editbox:SetHeight(20)
	editbox:SetPoint("BOTTOMLEFT", 0, 0)
	table.insert(options.widgets, widget)

	local widget = CreateFrame("Frame", nil, options)
	widget:SetHeight(35)
	widget:SetWidth(160)
	local editbox = CreateFrame("EditBox", "PRRange_SecSpell", widget, "InputBoxTemplate")
	local font = editbox:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
	font:SetText(L["Secondary Spell:"])
	font:SetPoint("TOPLEFT", widget, "TOPLEFT", 0, 0)
	editbox:SetAutoFocus(nil)
	editbox:SetWidth(160)
	editbox:SetHeight(20)
	editbox:SetPoint("BOTTOMLEFT", 0, 0)
	table.insert(options.widgets, widget)

	local cancel = CreateFrame("Button", "PRRange_Cancel", options, "PRButtonTemplate")
	cancel:SetText(L["Cancel"])
	cancel:SetPoint("BOTTOMRIGHT", 0, 5)
	cancel:SetScript("OnClick", function() self:OnShow() end)
	cancel:Show()
	
	local save = CreateFrame("Button", "PRRange_Save", options, "PRButtonTemplate")
	save:SetText(L["Save"])
	save:SetPoint("BOTTOMRIGHT", cancel, "BOTTOMLEFT", -10, 0)
	save:SetScript("OnClick", function() self:SaveOptions() end)
	save:Show()

	for idx,widget in ipairs(options.widgets) do
		widget:Show()
		if idx == 1 then
			widget:SetPoint("TOPLEFT", 0, 0)
		else
			widget:SetPoint("TOPLEFT", options.widgets[idx - 1], "BOTTOMLEFT", 0, -15)
		end
	end
end

function Range:OnShow()
	local profile = PerfectRaid.db.profile

	PRRange_Enable:SetChecked(profile.RangeCheck)
	PRRange_Rate:SetValue(profile.RangeRate)
	PRRange_PriAlpha:SetValue(profile.RangePriAlpha)
	PRRange_SecAlpha:SetValue(profile.RangeSecAlpha)
	PRRange_OutAlpha:SetValue(profile.RangeOutAlpha)
	PRRange_PriSpell:SetText(profile.RangePriSpell or "")
	PRRange_SecSpell:SetText(profile.RangeSecSpell or "")
end

function Range:SaveOptions()
	local profile = PerfectRaid.db.profile
	
	profile.RangeCheck = PRRange_Enable:GetChecked() or false
	profile.RangeRate = PRRange_Rate:GetValue()
	profile.RangePriAlpha = PRRange_PriAlpha:GetValue()
	profile.RangeSecAlpha = PRRange_SecAlpha:GetValue()
	profile.RangeOutAlpha = PRRange_OutAlpha:GetValue()

	local prispell = PRRange_PriSpell:GetText()
	local secspell = PRRange_SecSpell:GetText()
	if prispell == "" then prispell = nil end
	if secspell == "" then secspell = nil end

	profile.RangePriSpell = prispell
	profile.RangeSecSpell = secspell

	if profile.RangeCheck then
		self:Enable()
	else
		self:Disable()
	end
end

